import { KeepSizeObject3D } from '@amcax/base';
import {
  constraintIconRenderer,
  ConstraintTag,
} from '@app-cad/common/utils/sketchTools/ConstraintIconRenderer';
import { Object3D, Vector3 } from 'three-legacy';

import { ctx2 } from '@app-cad/module';
import { ConstraintIcon } from './ConstraintIcon';

// 约束图标，可能包含多个挂载至同一位置的图标
export class ConstraintIconGroup extends KeepSizeObject3D {
  icons: ConstraintIcon[] = [];

  constructor(constraints: ConstraintTag[]) {
    super(ctx2.viewer.sceneSetup.camera, true);
    const { frame, transformMatrix } = constraintIconRenderer;

    // 被分到同一组的约束，其位置和offset都相同
    // 将点转换为3d坐标，position的转化需要完整的坐标变换，但offset的转化需要仅旋转，因此不能直接使用SketcFrame的方法
    this.position.set(
      ...new Vector3(...constraints[0].position, 0)
        .applyMatrix4(transformMatrix.clone().setPosition(...frame[0]))
        .toArray(),
    );

    const count = constraints.length;

    this.icons = constraints.map((c, index) => {
      const icon = new ConstraintIcon(c);

      const isTop = index % 2 === 0;
      const rowIndex = Math.floor(index / 2);

      const offsetUnit = 0.7;

      const y = isTop ? offsetUnit : -offsetUnit;

      const topCount = Math.ceil(count / 2);
      const bottomCount = Math.floor(count / 2);

      const topX = (-(topCount - 1) / 2 + rowIndex) * offsetUnit * 2;
      const bottomX = (-(bottomCount - 1) / 2 + rowIndex) * offsetUnit * 2;

      const offset = c.offset ?? [0, 1];

      // offset表示偏移方向，对应地，此处是offset的偏移方向对应的二维基向量
      const offsetY = new Vector3(...offset, 0);
      const offsetX = new Vector3(0, 0, 1).cross(offsetY);

      icon.position.set(
        ...offsetX
          .clone()
          .multiplyScalar(isTop ? topX : bottomX)
          .add(offsetY.clone().multiplyScalar(y))
          .applyMatrix4(transformMatrix)
          .toArray(),
      );

      return icon;
    });

    this.add(...this.icons);
  }

  addTo(parent: Object3D) {
    parent.add(this);
  }

  // 不释放 material，材质会被复用
  destroy() {
    this.parent?.remove(this);
    this.clear();
  }
}
